package com.softWang.system.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.softWang.common.base.BaseServiceMy;
import com.softWang.common.base.LoginUser;
import com.softWang.common.exception.LogicException;
import com.softWang.common.utils.SecurityUtils;
import com.softWang.system.mapper.SystemMenuMapper;
import com.softWang.system.mapper.SystemRoleMenuMapper;
import com.softWang.system.mapper.SystemTenantMenuMapper;
import com.softWang.system.controller.vo.systemMenu.SystemMenuGetMenuTreeParam;
import com.softWang.system.controller.vo.systemMenu.SystemMenuQueryAllParam;
import com.softWang.system.controller.vo.systemMenu.SystemMenuQueryAllResult;
import com.softWang.system.po.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SystemMenuService extends BaseServiceMy<SystemMenu> {
    @Resource
    private SystemMenuMapper systemMenuMapper;
    @Resource
    private SystemRoleMenuMapper systemRoleMenuMapper;
    @Resource
    private SystemTenantMenuMapper systemTenantMenuMapper;

    /**
     * 分页条件查询
     * @param param
     * @return
     */
    public List<SystemMenuQueryAllResult> queryall(SystemMenuQueryAllParam param){
        param.startPage();
        List<SystemMenuQueryAllResult> results=systemMenuMapper.queryall(param);
        return results;
    }

    /**
     * 插入菜单
     * @param menu 菜单信息
     * @return 菜单id
     */
    @Transactional
    public Long add(SystemMenu menu) {
        if(menu.getPid() == null){ menu.setPid(0L); }
        // 验证参数信息
        valdation(menu);
        // 设置参数信息
        menu.setState(SystemParameter.State.NORMAL.getCode());

        SystemMenu parent = null;
        if(menu.getPid() != 0) {
            parent = systemMenuMapper.selectById(menu.getPid());
            menu.setUrl(parent.getUrl() + "/" + menu.getMkey());
        }else{
            menu.setUrl("/"+menu.getMkey());
        }

        systemMenuMapper.insert(menu);

        //更新treecode
        String treecode = menu.getPid() == 0 ? menu.getId().toString() + "," : parent.getTreecode() + menu.getId() + ",";
        menu.setTreecode(treecode);

        systemMenuMapper.updateById(menu);

        return menu.getId();
    }


    /**
     * 修改菜单
     * @param menu 菜单信息
     * @return
     */
    @Transactional
    public Long edit(SystemMenu menu) {
        if(menu.getPid() == null){ menu.setPid(0L); }
        // 验证参数信息
        valdation(menu);

        SystemMenu old = systemMenuMapper.selectById(menu.getId());
        if(old == null){
            throw new LogicException("菜单不存在");
        }

        menu.setTreecode(old.getTreecode());

        SystemMenu parent = null;
        if(menu.getPid() != 0) {
            parent = systemMenuMapper.selectById(menu.getPid());
            menu.setUrl(parent.getUrl() + "/" + menu.getMkey());
        }else{
            menu.setUrl("/"+menu.getMkey());
        }

        systemMenuMapper.updateById(menu);

        // 判断上级部门是否修改，修改后需要更新treecode
        if(menu.getPid() != old.getPid()){
            // 验证上级菜单是否存在
            if(parent == null){
                throw new LogicException("上级菜单不存在");
            }
            // 不能选择自己或自己的子部门作为上级部门
            if(parent.getId() == menu.getId() || parent.getTreecode().contains(old.getTreecode())){
                throw new LogicException("不能选择自己或自己的子菜单作为上级菜单");
            }
            String selfTreecodeNew = menu.getPid() == 0 ? menu.getId().toString() + "," : parent.getTreecode() + menu.getId() + ",";

            // 更新自己及子部门的treecode
            List<SystemMenu> selfAndChildren =systemMenuMapper.selectList(
                    Wrappers.lambdaQuery(SystemMenu.class)
                            .likeRight(SystemMenu::getTreecode, old.getTreecode()));
            selfAndChildren.forEach(d -> {
                String treeCodeOld = d.getTreecode();
                String treeCodeNew = selfTreecodeNew + treeCodeOld.substring(old.getTreecode().length(), treeCodeOld.length());
                d.setTreecode(treeCodeNew);
            });

            systemMenuMapper.updateById(selfAndChildren);
        }


        return menu.getId();
    }

    /**
     * 获取详情
     * @param id id
     * @return
     */
    public SystemMenu getById(Long id) {
        return systemMenuMapper.selectById(id);
    }

    /**
     * 删除部门
     * @param ids 部门id列表
     * @return void
     */
    @Transactional
    public void del(List<Long> ids) {
        //菜单下有子菜单不能删除
        Long childNum = systemMenuMapper.selectCount(Wrappers.lambdaQuery(SystemMenu.class)
                .in(SystemMenu::getPid,ids));
        if(childNum > 0){
            throw new LogicException("该菜单下有子菜单或按钮，不能删除");
        }
        //删除菜单
        systemMenuMapper.deleteBatchIds(ids);
        //删除角色菜单关系
        systemRoleMenuMapper.delete(new LambdaQueryWrapper<SystemRoleMenu>()
               .in(SystemRoleMenu::getMenuid, ids));
    }


    private void valdation(SystemMenu param){
        // 验证同一父级菜单下名称唯一性
        Long num = systemMenuMapper.selectCount(
                new LambdaQueryWrapper<SystemMenu>()
                        .eq(SystemMenu::getMname, param.getMname())
                        .eq(SystemMenu::getPid, param.getPid())
                        .ne(param.getId()!=null,SystemMenu::getId, param.getId()));
        if (num > 0) {
            throw new LogicException("名称已存在!");
        }
        // 验证后台权限唯一性
        /*if(param.getPermission()!=null && !"".equals(param.getPermission().trim())) {
            Long keyNum = systemMenuMapper.selectCount(
                    new LambdaQueryWrapper<SystemMenu>()
                            .eq(SystemMenu::getPermission, param.getPermission())
                            .ne(param.getId() != null, SystemMenu::getId, param.getId()));
            if (keyNum > 0) {
                throw new LogicException("后台权限标识已存在!");
            }
        }*/
    }

    public List<SystemMenu> getMenuTree(SystemMenuGetMenuTreeParam param) {
        List<SystemMenu> menus = new ArrayList<>();
        // 判断是否是超级管理员
        Boolean isSysAdmin = SecurityUtils.isSysAdmin();
        // 判断是否系统租户
        Boolean isSystemTenant = SecurityUtils.isSystemTenant();
        if (isSysAdmin || isSystemTenant) {
            menus = systemMenuMapper.selectList(Wrappers.lambdaQuery(SystemMenu.class)
                    .in(!param.isHasButton(), SystemMenu::getType, Arrays.asList(SystemMenu.Type.Kind.getCode(), SystemMenu.Type.Menu.getCode()))
                    .orderByAsc(SystemMenu::getSort)
                    .orderByDesc(SystemMenu::getId));
            return menus;
        }
        // 普通租户，只能获取租户自己拥有的菜单
        LoginUser loginUser = SecurityUtils.getLoginUser();
        Long tenantId = loginUser.getTenantId();
        List<SystemTenantMenu> tenantMenus = systemTenantMenuMapper.selectList(Wrappers.lambdaQuery(SystemTenantMenu.class)
                .eq(SystemTenantMenu::getTenantId, tenantId));
        if(tenantMenus == null || tenantMenus.isEmpty()){
            // 租户菜单为空，返回空列表
            return menus;
        }

        List<Long> menuIds = tenantMenus.stream()
                .map(SystemTenantMenu::getMenuId)
                .distinct()
                .collect(Collectors.toList());
        menus = systemMenuMapper.selectList(Wrappers.lambdaQuery(SystemMenu.class)
                .in(SystemMenu::getId, menuIds)
                .in(!param.isHasButton(), SystemMenu::getType, Arrays.asList(SystemMenu.Type.Kind.getCode(), SystemMenu.Type.Menu.getCode()))
                .orderByAsc(SystemMenu::getSort)
                .orderByDesc(SystemMenu::getId));
        return menus;
    }
}
